from libavg import avg, ui
import math
from Box2D.Box2D import b2_dynamicBody, b2Vec2
import Constants
from Specials import Item
from random import randint
import components

class Cannon(avg.DivNode):
    
    def __init__(self, parent, cannonId, **kwargs):
        super(Cannon, self).__init__(**kwargs)
        
        if parent:
            parent.appendChild(self)
            self.__level = parent
        
        w = Constants.CANNON_SIZE_DEFAULT.x
        h = Constants.CANNON_SIZE_DEFAULT.y 
        self.__cannonId = cannonId 
        self.__ignoreScale = True
        self.__ignoreRotation = False

        self.size = (1.5 * w, 2 * h)
        self.pos = (self.__level.size.x/2 - self.size[0]/2, 0 if self.__cannonId == 0 else self.__level.size.y - self.size[1])
        self.angle = math.pi if self.__cannonId == 0 else 0
        
        self.__img = avg.ImageNode(parent=self, size = (w, h), pos=(0.25*w, h), href="resources/textures/cannon/cannon_body.png")
        self.__barrel = avg.DivNode(parent=self, size=(w/3, 3*h), pos=(0.25*w+w/2-w/6, h/2))
        self.__barrelImg = avg.ImageNode(parent=self.__barrel, size = (w/3, h/2+10), href="resources/textures/cannon/cannon_head.png")
        self.__stock = Stock(parent=self, length=1)
        
        self.__cannonMover = ui.TransformRecognizer(
                eventNode=self.__barrelImg, 
                detectedHandler=self.__onDetected,
                moveHandler=self.__onRotate,
                upHandler=self.__onUp
        )
        
        self.__doubleTapRecognizer1 = ui.DoubletapRecognizer(
                node=self.__barrel, 
                detectedHandler=self.__onDoubleTapFire
        )
        
        self.__doubleTapRecognizer2 = ui.DoubletapRecognizer(
                node=self.__stock, 
                detectedHandler=self.__onDoubleTapFire
        )
         
        self.__doubleTapRecognizer3 = ui.DoubletapRecognizer(
                node=self.__img, 
                detectedHandler=self.__onDoubleTapFire
        )

    def __onDoubleTapFire(self, event):
        itemId = self.__stock.first()
        
        if(itemId > -1):
            cHeadPos = self.__barrelImg.getAbsPos(self.__barrelImg.pos)
            tAngle = self.__barrel.angle + (self.angle - math.pi/2)
            
            if self.__barrel.angle > 0:
                offset = -(abs(math.sin(tAngle + (math.pi / 2))) * 20) if math.sin(tAngle + (math.pi / 2)) != 0 else 0
            else:
                offset = (abs(math.sin(tAngle + (math.pi / 2))) * 20) if math.sin(tAngle + (math.pi / 2)) != 0 else 0

            if self.__cannonId == 1:
                cHeadPos = avg.Point2D(cHeadPos.x + math.cos(tAngle + (math.pi / 2)) * ((self.__barrelImg.size[0] - 40) / 2), cHeadPos.y - (20 + offset))    
            elif self.__cannonId == 0:
                cHeadPos = avg.Point2D((cHeadPos.x - self.__barrelImg.size[0]) - math.cos(tAngle + (math.pi / 2)) * ((self.__barrelImg.size[0] - 40) / 2), cHeadPos.y - (20 - offset))
                
            self.__level.bubbles.append(Bubble(parent = self.__level, position=cHeadPos, itemId=itemId, cannonId=self.__cannonId, speed=2, angle=tAngle))
        
    def __rotateNodeOnScreen(self, node, transform):
        xmove = transform.trans.x
        if xmove < 0:
            if node.angle > -0.4: 
                node.angle = node.angle - 0.02 * math.pi
        elif xmove > 0:
            if node.angle < 0.4:
                node.angle = node.angle + 0.02 * math.pi
            
    def __onDetected(self, event):
        pass

    def __onRotate(self, transform):
        if self.__ignoreScale:
            transform.scale = 1
        if self.__ignoreRotation:
            transform.rot = 0
        self.__rotateNodeOnScreen(self.__barrel, transform)

    def __onUp(self, transform):
        pass
    
    def destroy(self):
        self.__stock.destroy()
        
        self.__cannonMover.enable(False)
        self.__cannonMover = None
        self.__doubleTapRecognizer1.enable(False)
        self.__doubleTapRecognizer1 = None
        self.__doubleTapRecognizer2.enable(False)
        self.__doubleTapRecognizer2 = None
        self.__doubleTapRecognizer3.enable(False)
        self.__doubleTapRecognizer3 = None
        
        self.__img.active = False
        self.__img.unlink(True)
        self.__img = None
        self.__barrelImg.active = False
        self.__barrelImg.unlink(True)
        self.__barrelImg = None
        self.__barrel.active = False
        self.__barrel.unlink(True)
        self.__barrel = None
        
        self.active = False
        self.unlink(True)
        
    def getLevel(self):
        return self.__level

class Bubble(avg.ImageNode):
    
    def __init__(self, parent, position, cannonId, itemId = -1,  angle = 0.0, speed = 1.0, **kwargs):
        super(Bubble, self).__init__(**kwargs)
        
        if parent:
            parent.appendChild(self)
            self.__level = parent

        self.__cannonId = cannonId
        self.__radius = 20.0
        self.__actorId = -1 
        self.__exploded = False
        if itemId > - 1:
            self.__itemId = itemId
        else:
            self.__itemId = randint(0, 5)

        self.pos = (position[0] + 6, position[1] + 6)   
        self.angle = angle
        self.size=(self.__radius * 2 - 12, self.__radius * 2 - 12)
        
        self.href="resources/textures/item/sItem_" + (self.__itemId).__str__() + ".png"
        self.__offX = 0
        self.__bubbleImg = avg.ImageNode(parent=self.__level, pos=position, angle=angle, size=(self.__radius * 2, self.__radius * 2), href="resources/textures/item/bubble.png")
        
        # create physical body
        self.__body = self.__level.world.Circle(position=(self.pos.x + self.__radius, self.pos.y + self.__radius), radius=self.__radius)
        self.__body.userData = self
        self.__body.type = b2_dynamicBody
        self.bullet = True
        self.__body.fixtures[0].filterData.maskBits = 175
        self.__body.fixtures[0].filterData.categoryBits = 32
        self.__body.angle = self.angle

        self.__body.linearVelocity = b2Vec2(math.cos(angle) * speed, math.sin(angle) * speed)
        self.__body.angularVelocity = 1.2
        
        self.__onFrameHandler = avg.Player.get().setOnFrameHandler(self.__update)
        
    def __update(self):
        self.__bubbleImg.pos = (self.__body.position.x * Constants.METERS2PIXELS - self.__radius + math.sin(self.__offX + math.pi / 3) * 1.5, self.__body.position.y * Constants.METERS2PIXELS - self.__radius + math.cos(self.__offX + math.pi / 3) * 1.5)
        self.pos = (self.__bubbleImg.pos[0]+6, self.__bubbleImg.pos[1]+6)
       
        self.angle = self.__body.angle
        self.__bubbleImg.angle = self.angle
        
        self.__offX += 0.1
        self.__body.position = ((self.__bubbleImg.pos.x + self.__radius) * Constants.PIXELS2METERS, (self.__bubbleImg.pos.y + self.__radius) * Constants.PIXELS2METERS)

        if(not self.__body.awake or self.__exploded):
            self.__level.DestroyBubble(self)
            self.__level.items.append(Item(parent=self.__level, position=self.__bubbleImg.pos, actorId=self.__actorId, itemId=self.__itemId))
            
    def onBeginContact(self, o):
        if isinstance(o, components.Actor.Ball) and not self.__exploded:
            self.__actorId = o.getActor()
            self.__exploded = True
            
    def onEndContact(self, o):
        pass
    
    def destroy(self):
        if self.__onFrameHandler:
            avg.Player.get().clearInterval(self.__onFrameHandler)
        self.__onFrameHandler = None
        
        self.__level.world.DestroyBody(self.__body)
        self.__body = None
        self.__bubbleImg.active = False
        self.__bubbleImg.unlink(True)
        self.active = False
        self.unlink(True)
        
        
class Stock(avg.DivNode):

    def __init__(self, parent, length, **kwargs):
        super(Stock, self).__init__(**kwargs)
        
        if parent:
            parent.appendChild(self)
            self.__level = parent.getLevel()
        
        self.size = (60, length * 60)
        self.pos = (parent.size.x / 2 - self.size.x / 2, parent.size.y - self.size.y)
        self.__length = length
        self.__stock = list()        
        
        self.__load()
        self.__onFrameHandler = None
        
    def first(self):
        if(self.__stock.__len__() == 0):
            return -1
        ammu = self.__stock.pop(0)
        ammu.destroy()
        self.__reorder()
        if self.__onFrameHandler:
            avg.Player.get().clearInterval(self.__onFrameHandler)
        self.__onFrameHandler = avg.Player.get().setInterval(5000, self.__load)
        return ammu.getItemId()
    
    def __load(self):
        if(self.__stock.__len__() < self.__length):
            newId = self.__level.getRandomItemID()
            ammu = Ammunition(parent=self, itemId=newId, size=(self.size.x, self.size.y / self.__length))
            ammu.reorder(self.__stock.__len__())
            self.__stock.append(ammu)
            
    def __reorder(self):
        tempStock = list()
        i = 0
        for ammu in self.__stock:
            tempStock.append(ammu)
            ammu.reorder(i)
            i += 1
        self.__stock = tempStock
    
    def destroy(self):
        if self.__onFrameHandler:
            avg.Player.get().clearInterval(self.__onFrameHandler)
        self.__onFrameHandler = None
        
        for ammu in self.__stock:
            ammu.destroy()
            
        self.active = False
        self.unlink(True)
        
class Ammunition(avg.DivNode):
    
    def __init__(self, parent, itemId, size, **kwargs):
        super(Ammunition, self).__init__(**kwargs)
        
        if parent:
            parent.appendChild(self)
        
        self.__itemId = itemId
        
        self.size = size
        
        self.__image = avg.ImageNode(parent=self, size=self.size, href = "resources/textures/item/sItem_" + (self.__itemId).__str__() + ".png")
        self.__image.pos = (10, 10)
        self.__image.size= (self.size.x - 20, self.size.y - 20)
        self.__bubbleImage = avg.ImageNode(parent=self, size=self.size, href = "resources/textures/item/bubble.png")

    def reorder(self, position):
        self.pos = (0, position * self.size.y)
        
    def getItemId(self):
        return self.__itemId    
        
    def destroy(self):
        self.__image.unlink(True)
        self.__image = None
        self.__bubbleImage.active = False
        self.__bubbleImage.unlink(True)
        self.__bubbleImage = None
        self.active = False
        self.unlink(True)
    